{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ec5aa9d2-9ceb-441e-b1b4-b70e3eabcab6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import random\n",
    "import torch.optim as optim\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4cbf93d3-fa82-4926-b724-5e9b10a7b728",
   "metadata": {},
   "outputs": [],
   "source": [
    "weights = [1.3, 2.9, 3.7]\n",
    "w_count = len(weights)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "3aa258d6-8fed-4910-8858-0f19504fdfe5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[7, 31, 17],\n",
       " [7, 11, 49],\n",
       " [7, 40, 7],\n",
       " [28, 27, 37],\n",
       " [19, 12, 50],\n",
       " [5, 41, 14],\n",
       " [25, 44, 24],\n",
       " [40, 28, 16],\n",
       " [2, 47, 19],\n",
       " [47, 37, 11]]"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_list = []\n",
    "for _ in range(100):\n",
    "    x_list.append([random.randint(1, 50) for _ in range(w_count)])\n",
    "\n",
    "x_list[0:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "463cb503-1cfd-4dfb-8080-c0019d6cd925",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 7., 31., 17.],\n",
       "        [ 7., 11., 49.],\n",
       "        [ 7., 40.,  7.],\n",
       "        [28., 27., 37.],\n",
       "        [19., 12., 50.],\n",
       "        [ 5., 41., 14.],\n",
       "        [25., 44., 24.],\n",
       "        [40., 28., 16.],\n",
       "        [ 2., 47., 19.],\n",
       "        [47., 37., 11.]], grad_fn=<SliceBackward0>)"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inputs = torch.tensor(x_list, dtype=torch.float32, requires_grad=True)\n",
    "inputs[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "b8a7b78b-987a-4227-acdd-0da6d8499ae9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[161.89999999999998,\n",
       " 222.3,\n",
       " 151.0,\n",
       " 251.6,\n",
       " 244.5,\n",
       " 177.2,\n",
       " 248.9,\n",
       " 192.39999999999998,\n",
       " 209.2,\n",
       " 209.10000000000002]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_list = []\n",
    "for x in x_list:\n",
    "    y_list.append(np.dot(x, weights))\n",
    "\n",
    "y_list[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "712e7ce4-bf76-406d-bf6f-888b5d60664a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([161.9000, 222.3000, 151.0000, 251.6000, 244.5000, 177.2000, 248.9000,\n",
       "        192.4000, 209.2000, 209.1000])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "targets = torch.tensor(y_list, dtype=torch.float32)\n",
    "targets[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "a54e1c69-e370-40a9-85aa-0f318b602447",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LNTXModel(\n",
       "  (linear): Linear(in_features=3, out_features=3, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 线性模型\n",
    "class LNTXModel(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(LNTXModel, self).__init__()\n",
    "        self.linear = nn.Linear(in_features=w_count, out_features=w_count)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.linear(x)\n",
    "\n",
    "# 实例化模型\n",
    "model = LNTXModel()\n",
    "model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "b8d0207f-8b12-4f49-a8af-b4fa7bd881f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义损失函数\n",
    "loss_fn = nn.MSELoss()\n",
    "\n",
    "# 定义优化器\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.0005)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "edca5a70-59fd-49bc-b223-eda9b8fc47af",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [100/1000], Loss: 0.0035\n",
      "Epoch [200/1000], Loss: 0.0019\n",
      "Epoch [300/1000], Loss: 0.0011\n",
      "Epoch [400/1000], Loss: 0.0006\n",
      "Epoch [500/1000], Loss: 0.0003\n",
      "Epoch [600/1000], Loss: 0.0002\n",
      "Epoch [700/1000], Loss: 0.0001\n",
      "Epoch [800/1000], Loss: 0.0001\n",
      "Epoch [900/1000], Loss: 0.0000\n",
      "Epoch [1000/1000], Loss: 0.0000\n",
      "Train done.\n"
     ]
    }
   ],
   "source": [
    "# 训练循环，迭代1000次\n",
    "num_epochs = 1000\n",
    "for epoch in range(num_epochs):\n",
    "    for i, x in enumerate(inputs):\n",
    "        # 前向传播\n",
    "        predictions = model(x)\n",
    "        \n",
    "        # 计算损失\n",
    "        loss = loss_fn(predictions, targets[i])\n",
    "        \n",
    "        # 清空梯度\n",
    "        optimizer.zero_grad()\n",
    "        \n",
    "        # 反向传播\n",
    "        loss.backward()\n",
    "        \n",
    "        # 更新参数\n",
    "        optimizer.step()\n",
    "    if (epoch+1) % 100 == 0:\n",
    "        print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))\n",
    "\n",
    "# 训练完成\n",
    "print('Train done.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "30b6b74c-2628-426e-bf76-3937ab87b418",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final weights:tensor([[1.3000, 2.9000, 3.7000],\n",
      "        [1.3000, 2.9000, 3.7001],\n",
      "        [1.3000, 2.9000, 3.6999]])\n",
      "Final bias:tensor([ 0.0003, -0.0036,  0.0067])\n"
     ]
    }
   ],
   "source": [
    "print(f'Final weights:{model.linear.weight.data}')\n",
    "print(f'Final bias:{model.linear.bias.data}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "a54b59ad-d4c9-4976-a023-c29b2a5dcb8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([7.9146, 7.8923, 7.8952], grad_fn=<ViewBackward0>)"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model(torch.tensor([float(1), float(1), float(1)]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4c63e97-a7bf-4f7d-97dd-8bc8103678dd",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
